/**
 * 给定二维平面上的点，再给定其中一个点
 * 要求求出包含该点的最长上升子序列，二维均严格上升
 * 
 * 首先考虑二维均严格上升子序列的长度如何求
 * 按x升序、y降序排序。
 * 并且令Di记录以数值i结尾的LIS的长度
 * 
 * for 每一个点p:
 *     t = D[1...p.y)的最大值
 *     D[p.y] = t + 1
 * 
 * 按这个顺序处理，必然每一次均可以得到当前点y坐标的D[y]   
 * 因此需要一个区间查询最大值、单点修改的数据结构，树状数组与线段树均可
 * 
 * 将二维均比指定点大的点放入一个数组，记作V
 * 对V求一个LIS
 * 
 * 再将二维均比指定点小的点放入一个数组，记作V
 * 再求一个LIS
 * 
 * 二者加起来再加一即可
 */
class Solution {

using vi = vector<int>;

struct SegTree{ // 线段树带延迟

using llt = long long;

int N;

using value_type = int;
vector<value_type> data; // 线段树

/// 从下往上计算信息，要变动
value_type _up_(const value_type & ls, const value_type & rs) {
    return max(ls, rs);
}

/// 初始化，清零，不用动
void init(int n) {
    data.assign((N = n) + 1 << 2, value_zero());
}

/// 这个函数不用动
void modify(int pos, const int & delta){
    _modify(1, 1, N, pos, delta);
}

/// 这个函数不用动
value_type query(int a, int b){
    return _query(1, 1, N, a, b);
}

/// 这个函数不用动
void build() {
    _build(1, 1, N);
}

/// 几乎不用动
value_type _query(int t, int s, int e, int a, int b) {
    if(a <= s and e <= b) {
        return data[t];
    }

    int mid = (s + e) >> 1;
    value_type ans = value_zero(); // 如果求最值，这里不能用zero
    if(a <= mid) ans = _up_(ans, _query(lson(t), s, mid, a, b));
    if(mid < b) ans = _up_(ans, _query(rson(t), mid + 1, e, a, b));
    return ans;
}

/// 几乎不用动
void _modify(int t, int s, int e, int pos, const int & delta) {
    if(s == e) {
        data[t] = delta;
        return;
    }

    int mid = (s + e) >> 1;
    if(pos <= mid) _modify(lson(t), s, mid, pos, delta);
    else _modify(rson(t), mid + 1, e, pos, delta);
    _pushUp(t);
    return;
}

/// 这个函数不用动
void _pushUp(int t) {
    data[t] = _up_(data[lson(t)], data[rson(t)]);
}

/// 几乎不用动
void _build(int t, int s, int e) {
    if(s == e) {
        int x; cin >> x;
        data[t] = value_type(x); // 注意提供value_type的初始化
        return; 
    }
    int mid = (s + e) >> 1;
    _build(lson(t), s, mid);
    _build(rson(t), mid + 1, e);
    _pushUp(t);
}

/// 辅助函数，视线段树信息类型而变动
static const value_type & value_zero() {
    static const value_type VALUE0 = 0;
    return VALUE0;
}

/// 这两个函数不用变动
static int lson(int x) {return x << 1;}
static int rson(int x) {return lson(x) | 1;}


}Bt;


struct _t{
    int x;
    int y;
    int pos;
};

int N;
vi Wx;
vi Wy;

public:
    int maxPathLength(vector<vector<int>>& coordinates, int k) {
        Wx.emplace_back(-1);
        Wy.emplace_back(-1);
        for(const auto & v : coordinates){
            Wx.emplace_back(v[0]);
            Wy.emplace_back(v[1]);
        }

        sort(Wx.begin(), Wx.end());
        Wx.erase(unique(Wx.begin(), Wx.end()), Wx.end());
        sort(Wy.begin(), Wy.end());
        Wy.erase(unique(Wy.begin(), Wy.end()), Wy.end());

        int limit = Wy.size();
        vi D(limit + 1, 0);

        vector<_t> V;
        for(int i=0;i<coordinates.size();++i){
            const auto & v = coordinates[i];
            if(v[0] > coordinates[k][0] and v[1] > coordinates[k][1]){
                int x = lower_bound(Wx.begin(), Wx.end(), v[0]) - Wx.begin();
                int y = lower_bound(Wy.begin(), Wy.end(), v[1]) - Wy.begin();
                V.push_back(_t{x, y, i});
            }
        }

        int ans = 0;
        if(not V.empty()){
            sort(V.begin(), V.end(), [](const _t & a, const _t & b){
                if(a.x != b.x) return a.x < b.x;
                if(a.y != b.y) return a.y > b.y;
                return a.pos < b.pos;
            });

            
            Bt.init(limit);
            Bt.modify(V[0].y, D[V[0].y] = 1);
            for(int i=1;i<V.size();++i){
                auto y = V[i].y;
                int t = 0;
                if(y > 1){
                    t = Bt.query(1, y - 1);
                }
                Bt.modify(y, D[y] = t + 1);
            }    

            ans = *max_element(D.begin(), D.end());        
        }

        V.clear();
        for(int i=0;i<coordinates.size();++i){
            const auto & v = coordinates[i];
            if(v[0] < coordinates[k][0] and v[1] < coordinates[k][1]){
                int x = lower_bound(Wx.begin(), Wx.end(), v[0]) - Wx.begin();
                int y = lower_bound(Wy.begin(), Wy.end(), v[1]) - Wy.begin();
                V.push_back(_t{x, y, i});
            }
        }

        if(not V.empty()){
            sort(V.begin(), V.end(), [](const _t & a, const _t & b){
                if(a.x != b.x) return a.x > b.x;
                if(a.y != b.y) return a.y < b.y;
                return a.pos < b.pos;
            });   

            D.assign(limit + 1, 0);
            Bt.init(limit);
            Bt.modify(V[0].y, D[V[0].y] = 1);
            for(int i=1;i<V.size();++i){
                auto y = V[i].y;

                int t = 0;
                if(y < limit){
                    t = Bt.query(y + 1, limit);
                }
                Bt.modify(y, D[y] = t + 1);
            }    

            ans += *max_element(D.begin(), D.end());                 
        }

        return ans + 1;
    }
};